package com.boot.tool;

import io.swagger.models.auth.In;

import java.util.*;

/**
 * 计算公式：[Y*D+C]-L
 *
 * @author
 */
public class JieQi {
    /**
     * 节气D值
     */
    private static final double D = 0.2422;
    /**
     * 20世纪的节气C值
     */
    private static final double[] C_20 = {6.11, 20.84, 4.6295, 19.4599, 6.3826, 21.4155, 5.59, 20.888, 6.318, 21.86,
            6.5, 22.2, 7.928, 23.65, 8.35, 23.95, 8.44, 23.822, 9.098, 24.218, 8.218, 23.08, 7.9, 22.6};
    /**
     * 21世纪的节气C值
     */
    private static final double[] C_21 = {5.4055, 20.12, 3.87, 18.73, 5.63, 20.646, 4.81, 20.1, 5.52, 21.04, 5.678,
            21.37, 7.108, 22.83, 7.5, 23.13, 7.646, 23.042, 8.318, 23.438, 7.438, 22.36, 7.18, 21.94};

    /**
     * 24节气
     */
    private static final String[] TERM = {"小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑",
            "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"};

    /**
     * 农历月份
     */
    private static final String[] MONTHLIST = {"十二（腊）月", "正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月"};
    /**
     * 节气缓存表
     */
    private static Map<Integer, Map<String, String>> termMap = new HashMap<Integer, Map<String, String>>();

    /**
     * 获取指定年份萨拉表
     *
     * @param year
     * @return
     */
    public Map<String, String> getYearTermMap(int year) {
        // 处理世纪C值
        double[] c = null;
        if (year > 1900 && year <= 2000) {
            c = C_20;
        } else if (year > 2000 && year <= 2100) {
            c = C_21;
        } else {
            throw new RuntimeException("不支持的年份:" + year + ",目前只支持1901年到2100年的时间范围");
        }
        // 从节气表中取
        Map<String, String> map = termMap.get(year);
        if (map != null) {
            return map;
        }
        // 节气表中无对应的节气数据，则计算生成
        synchronized (TERM) {
            map = termMap.get(year);
            if (map == null) {
                int y = year % 100;
                map = new HashMap<String, String>();
                for (int k = 0; k < 24; k++) {
                    // 计算节气日期，计算公式：[Y*D+C]-L
                    int date = 0;
                    if (k < 2 || k > 22) {
                        date = (int) (y * D + c[k]) - (int) ((y - 1) / 4);
                    } else {
                        date = (int) (y * D + c[k]) - (int) (y / 4);
                    }
                    // 记录计算结果
//                    map.put(getTermKey(k / 2 + 1, date), TERM[k]);
                    map.put(TERM[k], getTermKey(k / 2 + 1, date));
                }
                // 计算结果添加到节气表
                termMap.put(year, map);
            }
        }
        return map;
    }

    /**
     * 获取农历月份范围
     *
     * @param year
     * @return
     */
    public List<String> getMonthRange(int year) {
        Map<String, String> jieQiList = getYearTermMap(year);
        List<String> monthRange = new ArrayList<>();
        for (int i = 0; i < MONTHLIST.length; i++) {
            String start = jieQiList.get(TERM[i * 2]);
//            String end = jieQiList.get(TERM[i * 2 + 1]);
            monthRange.add(start);
        }
        return monthRange;
    }

    /**
     * 组装节气存储key
     *
     * @param month
     * @param date
     * @return
     */
    private static String getTermKey(int month, int date) {
        return month + "-" + date;
    }

    /**
     * 根据一个公里日期 返回对应农历月份
     *
     * @param date 包含年月日
     * @return 农历月份
     */
    public int getNontLi(String date) {
        date = date.split(" ")[0];
        int year = Integer.parseInt(date.split("-")[0]);
        int month = Integer.parseInt(date.split("-")[1]);
        int day = Integer.parseInt(date.split("-")[2]);
        List<String> monthRange = getMonthRange(year);
        Date my = new Date(year, month, day);
        int monthIndex = 0;
        for (int i = 0; i < monthRange.size(); i++) {
            Date date1 = new Date(year, Integer.parseInt(monthRange.get(i).split("-")[0]), Integer.parseInt(monthRange.get(i).split("-")[1]));
            if (i + 1 > 11) {
                if (date1.before(my)) {
                    monthIndex = i;
                    break;
                }
            } else {
                Date nextDate = new Date(year, Integer.parseInt(monthRange.get(i + 1).split("-")[0]), Integer.parseInt(monthRange.get(i + 1).split("-")[1]));
                if (date1.before(my) && nextDate.after(my)) {
                    monthIndex = i == 0 ? 12 : i;
                    break;
                }
            }
        }
        return monthIndex;
    }
}